#include "stdinc.h"
#include "cvar.h"

#include "CmdList.h"

static TCVar cvars[CVAR_COUNT];

bool cvar_setget(int flags, CCmdList::Parser *parser);
bool cvar_fov(int flags, CCmdList::Parser *parser);
bool cvar_quit(int flags, CCmdList::Parser *parser);

#define MAKE_FLAGS(x,y) ((x) + ((y)<<16))

CCmdList::TCmdStruct cvar_list[] = {
	{"vid_width",			cvar_setget,		MAKE_FLAGS( CVAR_VID_WIDTH,			CVAR_TYPE_INT),		"Video width"},
	{"vid_height",			cvar_setget,		MAKE_FLAGS( CVAR_VID_HEIGHT,		CVAR_TYPE_INT),		"Video height"},
	{"vid_xpos",			cvar_setget,		MAKE_FLAGS( CVAR_VID_XPOS,			CVAR_TYPE_INT),		"Window position x"},
	{"vid_ypos",			cvar_setget,		MAKE_FLAGS( CVAR_VID_YPOS,			CVAR_TYPE_INT),		"Vindow position y"},
	{"vid_bpp",				cvar_setget,		MAKE_FLAGS( CVAR_VID_BPP,			CVAR_TYPE_INT),		"Video bits per pixel"},
	{"vid_fullscreen",		cvar_setget,		MAKE_FLAGS( CVAR_VID_FULLSCREEN,	CVAR_TYPE_INT),		"Video fullscreen"},

	{"fov",					cvar_fov,			0,														"Fov"},


	{"quit",				cvar_quit,			0,														"Quits the application"},

	{NULL, NULL, 0, NULL}

};

TCVar* cvar_get(int id)
{
	ASSERT(id>=0);
	ASSERT(id<CVAR_COUNT);

	return &cvars[id];
}

int cvar_get_int(int id)
{
	ASSERT(id>=0);
	ASSERT(id<CVAR_COUNT);

	return cvars[id].asInt;
}

float cvar_get_float(int id)
{
	ASSERT(id>=0);
	ASSERT(id<CVAR_COUNT);

	return cvars[id].asFloat;
}

bool cvar_get_bool(int id)
{
	ASSERT(id>=0);
	ASSERT(id<CVAR_COUNT);

	return cvars[id].asBool;
}

char* cvar_get_string(int id)
{
	ASSERT(id>=0);
	ASSERT(id<CVAR_COUNT);

	return cvars[id].asString;
}

void cvar_set_int(int id, int var)
{
	ASSERT(id>=0);
	ASSERT(id<CVAR_COUNT);

	cvars[id].type = CVAR_TYPE_INT;
	cvars[id].asInt = var;
}

void cvar_set_float(int id, float var)
{
	ASSERT(id>=0);
	ASSERT(id<CVAR_COUNT);

	cvars[id].type = CVAR_TYPE_FLOAT;
	cvars[id].asFloat = var;
}

void cvar_set_bool(int id, bool var)
{
	ASSERT(id>=0);
	ASSERT(id<CVAR_COUNT);

	cvars[id].type = CVAR_TYPE_BOOL;
	cvars[id].asBool = var;
}

void cvar_set_string(int id, char* var)
{
	ASSERT(id>=0);
	ASSERT(id<CVAR_COUNT);

	cvars[id].type = CVAR_TYPE_STRING;
	cvars[id].asString = var;
}

bool cvar_setget(int flags, CCmdList::Parser *parser)
{
	int type = flags >> 16;
	int id = flags & 0xffff;

	if (parser->EndCmd())
	{
		switch (type)
		{
		case CVAR_TYPE_INT:
			LOG->Console("%s: %d", cvars[id].asInt);
			return true;

		case CVAR_TYPE_FLOAT:
			LOG->Console("%s: %.5", cvars[id].asFloat);
			return true;

		case CVAR_TYPE_BOOL:
			LOG->Console("%s: %s", cvars[id].asBool?"TRUE":"FALSE");
			return true;

		case CVAR_TYPE_STRING:
			LOG->Console("%s: %s", cvars[id].asString);
			return true;

		default:
			ASSERT(0);
			return false;
		}
	}

	switch (type)
	{
	case CVAR_TYPE_INT:
		if (!parser->GetInt(cvars[id].asInt))
			return false;
		return true;

	case CVAR_TYPE_FLOAT:
		if (!parser->GetFloat(cvars[id].asFloat))
			return false;
		return true;

	case CVAR_TYPE_BOOL:
		if (!parser->GetBool(cvars[id].asBool))
			return false;
		return true;

	case CVAR_TYPE_STRING:
		{
			if (!parser->GetBool(cvars[id].asBool))
				return false;
			return true;
		}

	default:
		ASSERT(0);
		return false;
	}

	return false;
}

bool cvar_fov(int flags, CCmdList::Parser *parser)
{
	return false;
}

bool cvar_quit(int flags, CCmdList::Parser *parser)
{
	cvar_set_bool(CVAR_QUIT, true);
	return true;
}

void cvar_register()
{
	//default values
	cvar_set_int(CVAR_VID_WIDTH,		800);
	cvar_set_int(CVAR_VID_HEIGHT,		600);
	cvar_set_int(CVAR_VID_XPOS,			10);
	cvar_set_int(CVAR_VID_YPOS,			10);
	cvar_set_int(CVAR_VID_BPP,			32);
	cvar_set_bool(CVAR_VID_FULLSCREEN,	false);

	cvar_set_float(CVAR_ZBUF_MIN,		0.1f);
	cvar_set_float(CVAR_ZBUF_MAX,		100.0f);
	cvar_set_float(CVAR_FOV,			45.0f);


	cvar_set_bool(CVAR_ACTIVE,			true);
	cvar_set_bool(CVAR_QUIT,			false);
	cvar_set_string(CVAR_WND_TITLE,		"Fili's OpenGL test");

	//register names
	CMDLIST->AddCmdList(cvar_list);
}

void cvar_unregister()
{
	for (int i=0; i<CVAR_COUNT; i++)
	{
		if (cvars[i].type == CVAR_TYPE_STRING)
		{
			SAFE_DEL_ARRAY(cvars[i].asString);
		}
	}
}
